﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;

namespace Gakita.View
{
    /* This class deals with drawing the startscreen, inbetweenlevelsscreen, and the endscreen. Also reads user input in those screens */
    class InfoView
    {
        private SpriteBatch _spriteBatch;
        private SpriteFont _infoFont;
        private SpriteFont _headerFont;
        private Texture2D _background;

        private KeyboardState oldkeyboardState      =       new KeyboardState();
        private String _usernameInput               =       "";

        public InfoView(GraphicsDeviceManager aGraphicsDevice, ContentManager aContentManager, SpriteBatch _aSpriteBatch)
        {
            _spriteBatch = _aSpriteBatch;

            _background = aContentManager.Load<Texture2D>("InfoBackground");
            _infoFont = aContentManager.Load<SpriteFont>("InfoFont");
            _headerFont = aContentManager.Load<SpriteFont>("HeaderFont");
        }

        /* This method draws the starting screen, which is shown when the game launches */
        public void DrawStartScreen(GraphicsDevice aGraphicsDevice)
        {
            Vector2 viewportSize = new Vector2(aGraphicsDevice.Viewport.Width, aGraphicsDevice.Viewport.Height);

            _spriteBatch.Begin();

            DrawStartBackground(viewportSize);

            // Draws "Please enter your name: "
            DrawStartText(viewportSize);

            DrawUsername(viewportSize);

            _spriteBatch.End();
        }

        /* This method draw the between level screen, which is show between levels */
        public void DrawBetweenLevelsScreen(GraphicsDevice aGraphicsDevice, int aTime, int aRank, Model.Level.Levels aCompletedLevel)
        {
            Vector2 viewportSize = new Vector2(aGraphicsDevice.Viewport.Width, aGraphicsDevice.Viewport.Height);

            aGraphicsDevice.Clear(new Microsoft.Xna.Framework.Color(142, 255, 255));

            _spriteBatch.Begin();

            // The header states which level the user just completed
            DrawHeader(viewportSize,aCompletedLevel);

            DrawTime(viewportSize,aTime);

            DrawRank(viewportSize,aRank);

            // The feedback text tells the user that he needs to press enter to continue
            DrawUserFeedbackText(viewportSize);

            _spriteBatch.End();
        }

        /* This method draws the end screen, which is shown after the user completes the last level */
        internal void DrawEndScreen(GraphicsDevice aGraphicsDevice)
        {
            Vector2 viewportSize = new Vector2(aGraphicsDevice.Viewport.Width, aGraphicsDevice.Viewport.Height);

            aGraphicsDevice.Clear(new Microsoft.Xna.Framework.Color(142, 255, 255));

            _spriteBatch.Begin();

            // Telling the user that the game is over
            DrawEndGame(viewportSize);

            // The feedback text tells the user that he needs to press enter to continue
            DrawUserFeedbackText(viewportSize);

            _spriteBatch.End();
        }

        private void DrawEndGame(Vector2 aViewportSize)
        {
            string endgameText = "Congratulations, you've completed Gakita";

            Vector2 textPosition = new Vector2(aViewportSize.X / 2 - _headerFont.MeasureString(endgameText).X / 2, 
                                               aViewportSize.Y / 2 - _headerFont.MeasureString(endgameText).Y);

            _spriteBatch.DrawString(_headerFont, endgameText, textPosition, Color.DeepPink);
        }

        private void DrawHeader(Vector2 aViewPortSize, Model.Level.Levels aCompletedLevel)
        {
            string headerText = "";

            switch (aCompletedLevel)
            {
                case Model.Level.Levels.first:
                    headerText = "First Level Completed!";
                    break;
                case Model.Level.Levels.second:
                    headerText = "Second Level Completed!";
                    break;
                case Model.Level.Levels.third:
                    headerText = "Third Level Completed!";
                    break;
                case Model.Level.Levels.fourth:
                    headerText = "Fourth Level Completed!";
                    break;
            }
            Vector2 textPosition = new Vector2(aViewPortSize.X / 2 - _infoFont.MeasureString(headerText).X / 2, 0 + aViewPortSize.Y / 8);

            _spriteBatch.DrawString(_headerFont, headerText, textPosition, Color.DeepPink);
        }

        private void DrawTime(Vector2 aViewPortSize, int aTime)
        {
            // The time is converted from milliseconds to seconds, then to a string which is cut to 5 characters.
            string timeText = "Time: " + ((double)aTime/1000).ToString().Substring(0,5) +" seconds";

            Vector2 textPosition = new Vector2(aViewPortSize.X / 4, 0 + aViewPortSize.Y / 8 * 3);

            _spriteBatch.DrawString(_infoFont, timeText, textPosition, Color.DeepPink);
        }

        private void DrawRank(Vector2 aViewPortSize,int aRank)
        {
            string rankText = "World Rank: ";

            // The standard value of the player rank is -1, which is changed once the player score has been uploaded 
            // and a new rank has been retrieved from the server. If the rank is still -1, it means the highscore 
            // is still being uploaded, so "Loading..." is shown instead of the rank
            if (aRank == -1)
            {
                rankText += "Loading...";
            }
            else
            {
                rankText += aRank +"th";
            }
            Vector2 textPosition = new Vector2(aViewPortSize.X / 4 , 0 + aViewPortSize.Y / 8 * 4 );

            _spriteBatch.DrawString(_infoFont, rankText, textPosition, Color.DeepPink);
        }

        private void DrawUserFeedbackText(Vector2 aViewPortSize)
        {
            string text = "Press Enter To Continue";

            Vector2 textPosition = new Vector2(aViewPortSize.X / 2 - _infoFont.MeasureString(text).X /2,                                                                                    aViewPortSize.Y - aViewPortSize.Y/8);

            _spriteBatch.DrawString(_infoFont, text, textPosition, Color.Green);
        }

        private void DrawStartText(Vector2 aViewPortSize)
        {
            String text = "Please enter your name:";
            Vector2 textPosition = new Vector2(aViewPortSize.X / 2 - _infoFont.MeasureString(text).X / 2,                                                                                   aViewPortSize.Y - aViewPortSize.Y / 4);

            _spriteBatch.DrawString(_infoFont, text, textPosition, Color.DeepPink);
        }

        private void DrawStartBackground(Vector2 aViewPortSize)
        {
            Rectangle destinationRectangle = new Rectangle(0, 0, (int)aViewPortSize.X, (int)aViewPortSize.Y);

            _spriteBatch.Draw(_background, destinationRectangle, Color.White);
        }

        private void DrawUsername(Vector2 aViewPortSize)
        {
            String text = _usernameInput;
            Vector2 textPosition = new Vector2(aViewPortSize.X / 2 - _infoFont.MeasureString(text).X / 2,                                                                                   aViewPortSize.Y - aViewPortSize.Y / 6);

            _spriteBatch.DrawString(_infoFont, text, textPosition, Color.DeepPink);
        }

        /* This method handles the userinput during the start screen. It keeps adding the userinput to a string. 
           Returns false until the user presses enter*/
        public bool IsUserDoneWithNameInput()
        {
            bool ret = false;

            KeyboardState keyboardState = Keyboard.GetState();

            // An array of the characters that are considered valid for the username
            Keys[] validinput = new Keys[25] { Keys.A, Keys.B, Keys.C, Keys.D, Keys.E, Keys.F, Keys.G, Keys.H, Keys.I, Keys.J, Keys.K,                                                      Keys.L, Keys.M, Keys.N, Keys.O, Keys.P, Keys.Q, Keys.R, Keys.S, Keys.T, Keys.U, Keys.V,                                                      Keys.W, Keys.Z, Keys.X };

            // Usernames longer then 14 characters isn't allowed.
            if (_usernameInput.Length < 14)
            {
                // If a valid key has been pressed, we check whether shift is being press aswell. If so, the letter is uppercase
                foreach (Keys key in validinput)
                {
                    if ((oldkeyboardState.IsKeyUp(key) && keyboardState.IsKeyDown(key)) && (keyboardState.IsKeyDown(Keys.LeftShift) ||                                keyboardState.IsKeyDown(Keys.RightShift)))
                    {
                        _usernameInput += key.ToString();
                    }
                    else if (oldkeyboardState.IsKeyUp(key) && keyboardState.IsKeyDown(key))
                    {
                        _usernameInput += key.ToString().ToLower();
                    }
                }
            }
            // Allowing the user to delete characters with backspace, assuming the inputstring contains any characters
            if (oldkeyboardState.IsKeyUp(Keys.Back) && keyboardState.IsKeyDown(Keys.Back))
            {
                if (_usernameInput.Length > 0)
                {
                    _usernameInput = _usernameInput.Remove(_usernameInput.Length - 1, 1);
                }
            }
            
            if (oldkeyboardState.IsKeyUp(Keys.Enter) && keyboardState.IsKeyDown(Keys.Enter))
            {
                ret = true;
            }
                

            oldkeyboardState = keyboardState;
            return ret;
        }

        /* This method is used during the inbetween level screen to check if the user pressed enter */
        public bool DidUserPressContinue()
        {
            bool ret = false;
            KeyboardState keyboardState = Keyboard.GetState();

            if (oldkeyboardState.IsKeyUp(Keys.Enter) && keyboardState.IsKeyDown(Keys.Enter))
            {
                ret = true;
            }
            oldkeyboardState = keyboardState;
            return ret;
        }

        public String GetNameInput()
        {
            return _usernameInput;
        }

    }
}
